package com.halden.TRPG.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.halden.TRPG.aop.LogInCheck;
import com.halden.TRPG.common.CodeEnum;
import com.halden.TRPG.common.MyException;
import com.halden.TRPG.common.Result;
import com.halden.TRPG.entity.MultipartFileParam;
import com.halden.TRPG.entity.RoomEntity;
import com.halden.TRPG.entity.RoomMusicEntity;
import com.halden.TRPG.entity.vo.RoomMusicUploadVo;
import com.halden.TRPG.entity.vo.RoomQueryVo;
import com.halden.TRPG.entity.vo.RoomResponseVo;
import com.halden.TRPG.entity.vo.RoomUpdateVo;
import com.halden.TRPG.service.*;
import com.halden.TRPG.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Path;
import java.sql.Blob;
import java.util.HashMap;

@RestController
@RequestMapping("/room")
@CrossOrigin
@Slf4j
public class RoomController {
    @Autowired
    private RoomService roomService;

    @Autowired
    private RoomImageService roomImageService;

    @Autowired
    private RoomMusicService roomMusicService;

    @Autowired
    private RoomNicknameService roomNicknameService;

    @Autowired
    private RoomKpService roomKpService;

    @Autowired
    private RoomUserService roomUserService;

    @Autowired
    private CardService cardService;

    @Autowired
    private RoomFileService roomFileService;

    @LogInCheck
    @PostMapping("/create/{uid}")
    public Result createRoom(@RequestBody RoomEntity roomEntity,
                             @PathVariable("uid") String uid) {
        CodeEnum code = roomService.create(roomEntity, uid);
        return Result.ok(200, "创建房间成功");
    }

    @LogInCheck
    @PostMapping("/join/{rid}/{uid}")
    public Result joinRoom(@PathVariable("rid") Long rid,
                           @PathVariable("uid") String uid) throws MyException {
        CodeEnum join = roomService.join(rid, uid);
        return Result.ok(200,"已向房主发送加入房间申请");
    }

    @LogInCheck
    @PostMapping("/remove/{rid}/{uid}")
    public Result removeRoom(@PathVariable("rid") Long rid,
                             @PathVariable("uid") String uid,
                             @RequestHeader(value = "Authorization") String token) throws MyException {
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum remove = roomService.remove(rid, uid);
        return Result.ok(200,"删除房间成功");
    }

    @LogInCheck
    @PostMapping("/page/{current}/{limit}/{uid}")
    public Result getPage(@PathVariable("current") Integer current,
                          @PathVariable("limit") Integer limit,
                          @PathVariable("uid") String uid,
                          @RequestBody(required = false) RoomQueryVo roomQueryVo,
                          @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        Page<RoomResponseVo> page = roomService.getPage(current, limit, uid, roomQueryVo);
        return Result.ok(200).add("page", page);
    }

    @LogInCheck
    @PostMapping("/back/join/{rid}/{uid}/{back}")
    public Result backForApplyJoinRoom(@PathVariable("rid") Long rid,
                                       @PathVariable("uid") String uid,
                                       @PathVariable("back") Boolean back) throws MyException {
        CodeEnum codeEnum = roomService.backForJoin(rid, uid, back);
        return Result.ok(200);
    }

    @LogInCheck
    @GetMapping("/joined/{current}/{limit}/{uid}")
    public Result getJoinedPage(@PathVariable("current") Integer current,
                                @PathVariable("limit") Integer limit,
                                @PathVariable("uid") String uid,
                                @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        Page<RoomResponseVo> joinedPage = roomService.getJoinedPage(current, limit, uid);
        return Result.ok(200).add("page",joinedPage);
    }

    @LogInCheck
    @GetMapping("/created/{current}/{limit}/{uid}")
    public Result getCreatedPage(@PathVariable("current") Integer current,
                                @PathVariable("limit") Integer limit,
                                @PathVariable("uid") String uid,
                                @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        Page<RoomResponseVo> page = roomService.getCreatedPage(current, limit, uid);
        return Result.ok(200).add("page",page);
    }

    @LogInCheck
    @PostMapping("/quit/{rid}/{uid}")
    public Result quit(@PathVariable("rid") Long rid,
                       @PathVariable("uid") String uid,
                       @RequestHeader(value = "Authorization") String token) throws MyException {
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        if (!JwtUtil.getUid(token).equals(uid)){
            return Result.error(401,"非本人操作");
        }
        CodeEnum codeEnum = roomService.quit(rid, uid);
        return Result.ok(200);
    }

    @LogInCheck
    @PostMapping("/image/upload/{rid}")
    public Result uploadImage(@RequestPart("file") MultipartFile image,
                               @PathVariable("rid") Long rid,
                               @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomImageService.uploadImage(image, rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @GetMapping("/image/get/{rid}")
    public Result getImages(@PathVariable("rid") Long rid){
        CodeEnum codeEnum = roomImageService.getImages(rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/image/delete/{rid}")
    public Result deleteImage(@PathVariable("rid") Long rid,
                              @RequestBody String url){
        CodeEnum codeEnum = roomImageService.deleteImage(rid, url);
        return Result.ok(200);
    }

    @LogInCheck
    @PostMapping("/chat/image/upload/{rid}")
    public Result uploadChatImage(@RequestPart("file") MultipartFile image,
                              @PathVariable("rid") Long rid,
                              @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomImageService.uploadChatImage(image, rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/music/create")
    public Result createMusic(@RequestBody RoomMusicUploadVo vo,
                              @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomMusicService.createMusic(vo);
        if (codeEnum == CodeEnum.SUCCESS) {
            return Result.ok(200).add("data",codeEnum.getData());
        } else {
            return Result.error(codeEnum.getCode(),codeEnum.getMessage());
        }
    }

    @LogInCheck
    @PostMapping("/music/upload/{rid}/{id}")
    public Result uploadMusic(@RequestPart("file") MultipartFile music,
                              @PathVariable("rid") Long rid,
                              @PathVariable("id") Long id,
                              @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomMusicService.uploadMusic(music,rid,id);
        if (codeEnum == CodeEnum.SUCCESS) {
            return Result.ok(200).add("data",codeEnum.getData());
        } else {
            return Result.error(codeEnum.getCode(),codeEnum.getMessage());
        }
    }

    @LogInCheck
    @PostMapping("/music/upload/cover/{id}")
    public Result uploadCover(@RequestPart("file") MultipartFile cover,
                              @PathVariable("id") Long id,
                              @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomMusicService.uploadCover(cover, id);
        if (codeEnum == CodeEnum.SUCCESS) {
            return Result.ok(200).add("data",codeEnum.getData());
        } else {
            return Result.error(codeEnum.getCode(),codeEnum.getMessage());
        }
    }


    @LogInCheck
    @GetMapping("/music/get/{rid}")
    public Result getMusics(@PathVariable("rid") Long rid){
        CodeEnum codeEnum = roomMusicService.getMusics(rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/music/delete/{rid}/{name}")
    public Result deleteMusic(@PathVariable("rid") Long rid,
                              @PathVariable("name") String name,
                              @RequestHeader(value = "Authorization") String token){
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomMusicService.deleteMusic(rid, name);
        return Result.ok(200);
    }


    @LogInCheck
    @GetMapping("/nickname/get/{rid}/{uid}")
    public Result getNickname(@PathVariable("rid") Long rid,
                              @PathVariable("uid") String uid){
        CodeEnum codeEnum = roomNicknameService.getNickname(rid, uid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/nickname/set/{rid}/{uid}/{nickname}")
    public Result setNickname(@PathVariable("rid") Long rid,
                              @PathVariable("uid") String uid,
                              @PathVariable("nickname") String nickname){
        CodeEnum codeEnum = roomNicknameService.setNickname(rid, uid, nickname);
        return Result.ok(200);
    }

    @LogInCheck
    @PostMapping("/update")
    public Result update(@RequestBody RoomUpdateVo roomUpdateVo,
                         @RequestHeader(value = "Authorization") String token) throws MyException {
        if (!JwtUtil.check(token)){
            return Result.error(401,"token过期，请重新登录");
        }
        CodeEnum codeEnum = roomService.updateRoom(roomUpdateVo, token);
        return Result.ok(200);
    }

    @LogInCheck
    @PostMapping("/setKp/{rid}/{kp}")
    public Result setKp(@PathVariable("rid") Long rid,
                        @PathVariable("kp") String kp){
        CodeEnum codeEnum = roomKpService.setKp(rid, kp);
        return Result.ok(200);
    }

    @LogInCheck
    @GetMapping("/getKp/{rid}")
    public Result getKp(@PathVariable("rid") Long rid){
        CodeEnum codeEnum = roomKpService.getKp(rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/stCard/{rid}/{uid}")
    public Result stCard(@PathVariable("rid") Long rid,
                         @PathVariable("uid") String uid,
                         @RequestBody String attributeStr){
        CodeEnum codeEnum = cardService.setCharacter(uid, rid, attributeStr);
        return Result.ok(200);
    }

    @LogInCheck
    @GetMapping("/getAttribute/{rid}/{uid}/{attributeName}")
    public Result getAttribute(@PathVariable("rid") Long rid,
                               @PathVariable("uid") String uid,
                               @PathVariable("attributeName") String attributeName){
        CodeEnum codeEnum = cardService.getAttribute(uid, rid, attributeName);
        return Result.ok(200).add("data",codeEnum.getData());
    }

    @LogInCheck
    @PostMapping("/chunkUpload/{rid}")
    public void fileChunkUpload(@PathVariable("rid") Long rid,
                                MultipartFileParam param,
                                HttpServletRequest request,
                                HttpServletResponse response){
        response.setContentType("text/html;charset=UTF-8");
        // response.setStatus对接前端插件
        //        200, 201, 202: 当前块上传成功，不需要重传。
        //        404, 415. 500, 501: 当前块上传失败，会取消整个文件上传。
        //        其他状态码: 出错了，但是会自动重试上传。
        try{
            /**
             * 判断前端Form表单格式是否支持文件上传
             */
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if(!isMultipart){
                //这里是我向前端发送数据的代码，可理解为 return 数据; 具体的就不贴了
                System.out.println("不支持的表单格式");
                response.setStatus(404);
                response.getOutputStream().write("不支持的表单格式".getBytes());
            }else {
                param.setTaskId(param.getIdentifier());
                CodeEnum codeEnum = roomFileService.chunkUploadByMappedByteBuffer(param, rid);//service层
                if (codeEnum == CodeEnum.SUCCESS) {
                    response.setStatus(200);
                    response.getWriter().print("上传成功");
                } else if (codeEnum == CodeEnum.NOT_SAME_FILE_EXCEPTION){
                    response.setStatus(501);
                } else {
                    response.setStatus(415);
                }
            }
            response.getWriter().flush();
        }
        catch (Exception e) {
            e.printStackTrace();
            System.out.println("上传文件失败");
            response.setStatus(415);
        }
    }

    @LogInCheck
    @GetMapping("/getFiles/{rid}")
    public Result getFiles(@PathVariable("rid") Long rid){
        CodeEnum codeEnum = roomFileService.getFileList(rid);
        return Result.ok(200).add("data",codeEnum.getData());
    }
}
